package cc.bluemc.modules.generateCode.service.impl;

import cc.bluemc.modules.generateCode.entity.ColumnBean;
import cc.bluemc.modules.generateCode.entity.GeneratorBean;
import cc.bluemc.modules.generateCode.entity.TableBean;
import cc.bluemc.modules.generateCode.service.IGenerateService;
import cc.bluemc.platform.utils.FreemarkerUtil;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class GenerateServiceImpl_MySQL implements IGenerateService{
	private Log log = LogFactory.getLog(this.getClass());
	@Autowired
	@Qualifier(value="jdbcTemplate_generate")
	private JdbcTemplate jdbcTemplate;
	  
	@Override
	public void generateCode(GeneratorBean generator) {
		  log.info("代码生成开始");
	       //查询表
	       List<TableBean> tableBeanList;
	       Map<String, Object> varMap;
	       if(null==generator.getTableNames()||generator.getTableNames().length==0){
	    		tableBeanList = getTableList(generator.getDbName());
	       }else{
	    	   String sql ="select * from tables where table_schema = ? AND table_name in('"+StringUtils.join(generator.getTableNames(),"','")+"')";
	    		tableBeanList= getTables(generator.getDbName(),sql,Arrays.asList(generator.getDbName()));
	       }
	       //模板
	       File tempDir = new File(generator.getTempPath()); 
	       File[] Files= tempDir.listFiles();
	       File[] temps;
	       String outputPath,tempOutputPath;
	       for (TableBean tableBean : tableBeanList) {
	    	   outputPath = generator.getOutputPath()+"/"+ tableBean.getTableNameNoDash()+"/";
	           varMap = new HashMap<String, Object>();
	           varMap.put("tableBean", tableBean);
	           varMap.put("schemaName", generator.getDbName());
	           varMap.put("packageBase", generator.getPackageBase());
	           //查询表列
	           tableBean.setColumnBeanList(getColumns(generator.getDbName(),tableBean));
	           
	           for(File f :Files ){
	        	   if(f.isDirectory()){
	        		   temps = f.listFiles();
	        		   for(File t : temps){
	        			   if(t.isFile()){
	        				   Template modelTemplate = FreemarkerUtil.getTemplate(t);
	        				   if(t.getName().indexOf("jsp")>0){
	        					   tempOutputPath = outputPath+f.getName()+"/"+ t.getName().replaceAll("([\\w]+)_([\\w]+).ftl", "$1.$2");
	        				   }else{
	        					   tempOutputPath = outputPath+f.getName()+"/"+ tableBean.getTableNameCapitalized()+StringUtils.capitalize(t.getName().replaceAll("([\\w]+)_([\\w]+).ftl", "$1.$2"));
	        				   }
	        				   FreemarkerUtil.outputProcessResult(tempOutputPath, modelTemplate, varMap);
	        				   
	        			   }
	        		   }
	        	   }
	           }
//	           Template modelTemplate = FreemarkerUtil.getTemplate(JDK_VERSION + "Temp/model.ftl");
//	           FreemarkerUtil.outputProcessResult(outputDirs+ tableBean.getTableNameNoDash() + "/entity/" + tableBean.getTableNameCapitalized() + ".java", modelTemplate, varMap);

	       }
	       log.info("代码生成结束");
	}
	
	@Override
	public TableBean getTable(String dbName, String tableName) {
		String sql="select * from tables where table_schema = ?  AND Table_name = ?";
		List<TableBean> list = getTables(dbName,sql,Arrays.asList(dbName,tableName));
		if(null!=list&&list.size()>0){
			TableBean tableBean = list.get(0);
			List<ColumnBean> columns = getColumns(dbName,tableBean);
			tableBean.setColumnBeanList(columns);
			return list.get(0);
		}
		return null;
	}
	@Override
	public List<TableBean> getTableList(String dbName) {
		String sql ="select * from tables where table_schema = ?";
        return getTables(dbName,sql,Arrays.asList(dbName));
	}
	@SuppressWarnings("unchecked")
	private List<TableBean> getTables(String dbName,String sql,List params){
		log.info("查询数据库……");
		//这是一个危险的操作啊
		jdbcTemplate.execute("USE information_schema");
		List<TableBean> tableBeanList = jdbcTemplate.query(sql.toString(), params.toArray(),
	                new RowMapper() {
	                    @Override
	                    public TableBean mapRow(ResultSet rs, int rowNum) throws SQLException {
	                        String tableName = rs.getString("table_name");
	                        String tableNameTrimed = tableName;
	                        //表名生成规则
	                        if (tableName.startsWith("t_")) {
	                            tableNameTrimed = tableName.substring(2);
	                        }
	                        
	                        TableBean bean = new TableBean();
	                        bean.setTableName(tableName);
	                        bean.setTableNameNoDash(delDash(tableNameTrimed));
	                        bean.setTableNameCapitalized(StringUtils.capitalize(bean.getTableNameNoDash()));
	                        bean.setTableComment(rs.getString("table_comment"));
	                        log.info("查询到表："+bean.toString());
	                        return bean;
	                    }
	                });
		jdbcTemplate.execute("USE "+getDbNameFromJdbcTemplate(jdbcTemplate,dbName));
        return tableBeanList;
	}
	@SuppressWarnings("unchecked")
	private List<ColumnBean> getColumns(String dbName, final TableBean tableBean) {
		jdbcTemplate.execute("USE information_schema");
		List<ColumnBean> list= jdbcTemplate.query("select * from COLUMNS where table_schema = ? and table_name = ?",
                new Object[]{dbName, tableBean.getTableName()},
                new RowMapper() {
                    @Override
                    public ColumnBean mapRow(ResultSet rs, int rowNum) throws SQLException {
                        ColumnBean bean = new ColumnBean();
                        String columnName = rs.getString("column_name");
                        bean.setColumnName(columnName);
                        bean.setColumnNameNoDash(delDash(columnName));
                        bean.setColumnNameCapitalized(StringUtils.capitalize(bean.getColumnNameNoDash()));
                        bean.setColumnComment(rs.getString("column_comment"));
                        if("pri".equalsIgnoreCase(rs.getString("column_key"))){
                        	bean.setPriKey(true);
                        	tableBean.setPriKey(bean.getColumnName());
                        }

                        String columnType = rs.getString("column_type").toLowerCase();
                         if (columnType.startsWith("int")) {
                            if(columnType.contains("unsigned")) {
                                bean.setColumnType("Long");
                                bean.setColumnTypeRsGetter("getLong");
                            } else {
                                bean.setColumnType("Integer");
                                bean.setColumnTypeRsGetter("getInt");
                            }
                        } else if (columnType.startsWith("bigint")) {
                            bean.setColumnType("Long");
                            bean.setColumnTypeRsGetter("getLong");
                        } else if (("timestamp").equals(columnType)||("datetime").equals(columnType)) {
                            bean.setColumnType("Date");
                            bean.setColumnTypeRsGetter("getDate");
                            tableBean.setHasDateColumn(true);
                        } else if (columnType.startsWith("float")) {
                            bean.setColumnType("Float");
                            bean.setColumnTypeRsGetter("getFloat");
                        } else if (columnType.startsWith("double")) {
                            bean.setColumnType("Double");
                            bean.setColumnTypeRsGetter("getDouble");
                        } else if (columnType.startsWith("decimal")) {
                            bean.setColumnType("BigDecimal");
                            bean.setColumnTypeRsGetter("getBigDecimal");
                            tableBean.setHasBigDecimal(true);
                        } else {
                        	 bean.setColumnType("String");
                             bean.setColumnTypeRsGetter("getString");
                        }

                        return bean;
                    }
                });
		jdbcTemplate.execute("USE "+getDbNameFromJdbcTemplate(jdbcTemplate,dbName));
		return list;
    }
   private  String delDash(String str) {
        String lowerCaseStr = str.toLowerCase();
        String[] noDashArray = StringUtils.split(lowerCaseStr, '_');
        StringBuilder noDash = new StringBuilder(noDashArray[0]);
        for (int i = 1; i < noDashArray.length; i++) {
            noDash.append(StringUtils.capitalize(noDashArray[i]));
        }
        return noDash.toString();
    }
   private String getDbNameFromJdbcTemplate(JdbcTemplate jdbcTemplate,String defaultName){
	   try {
		String connectionInfo = jdbcTemplate.getDataSource().getConnection().toString();
		String dbName=connectionInfo.replaceAll(".+/(.+)\\?.+", "$1");
		return dbName;
	   } catch (SQLException e) {
		log.info("从JdbcTemplate中获取库名失败，返回默认库名");
	}
	return defaultName;
   }
}
